home *** CD-ROM | disk | FTP | other *** search
/ Amiga Game-Power / Amiga Game-Power.iso / pd mix ii / click to front / heliosmouse / heliosmouse.c < prev    next >
C/C++ Source or Header  |  1994-05-20  |  9KB  |  281 lines

  1. /*
  2.  *  HeliosMouse.c   Installs an input handler that activates windows when
  3.  *                  you move the mouse over inactive ones.
  4.  *
  5.  *             Copyright (c) 1987 by Davide P. Cervone
  6.  *  You may use this code provided this copyright notice is left intact.
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include <libraries/dos.h>
  11. #include <exec/io.h>
  12. #include <exec/memory.h>
  13. #include <exec/interrupts.h>
  14. #include <devices/input.h>
  15. #include <devices/inputevent.h>
  16.  
  17. static char *program  = "HeliosMouse";
  18. static char *version  = "v1.0";
  19. static char *date     = "June 1987";
  20. static char *author   = "Copyright (c) 1987 by Davide P. Cervone";
  21.  
  22. static char *PortName = "HeliosPort";
  23. static char *handler  = "L:Helios-Handler";    /* the handler file */
  24. #define HANDLER            &(handler[2])       /* without the "L:" */
  25.  
  26.  
  27. /*
  28.  *  This is the structure that holds the handler information between calls
  29.  *  to HeliosMouse.  We create a named, public message-port that points to
  30.  *  an instance of this structure so that we can find this information
  31.  *  when we are asked to remove the handler.  The PortName is stored here 
  32.  *  (NamedPort->mp_Node.ln_Name uses this area for its name).   The other 
  33.  *  data are what we need in order to remove the handler and clean up properly.
  34.  */
  35.  
  36. struct HandlerBlock
  37. {
  38.    char *PortName;                  /* name of the public, named message-port */
  39.    struct Interrupt Handler;        /* the handler added to the handler chain */
  40.    struct IntuitionBase *Ibase;     /* library base used by the handler */
  41.    struct LayersBase *Lbase;        /* library base used by the handler */
  42.    long Segment;                    /* pointer from LoadSeg() */
  43. };
  44. #define HANDLERINFOSIZE     sizeof(struct HandlerBlock)
  45. #define NAMESIZE            (strlen(PortName)+1)
  46.  
  47. extern struct MsgPort *CreatePort();
  48. extern struct IOStdReq *CreateStdIO();
  49. extern struct MsgPort *FindPort(), *CreatePort();
  50. extern APTR AllocMem();
  51. extern long LoadSeg();
  52.  
  53. #define INTUITION_REV   0L
  54. #define LAYERS_REV      0L
  55.  
  56. struct IntuitionBase  *IntuitionBase = NULL;
  57. struct LayersBase     *LayersBase    = NULL;
  58. extern struct SysBase *SysBase;
  59.  
  60. struct MsgPort *InputPort = NULL;     /* Port used to talk to Input.Device */
  61. struct IOStdReq *InputBlock = NULL;   /* request block used with Input.Device */
  62. LONG InputDevice = 0;                 /* flag whether Input.Device is open */
  63. struct MsgPort *NamedPort = NULL;     /* holds info needed to remove handler */
  64. struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
  65.  
  66.  
  67. /*
  68.  *  DoExit()
  69.  *
  70.  *  General purpose exit routine.  If 's' is not NULL, then print an
  71.  *  error message with up to three parameters.  Free any memory, close
  72.  *  any open device, delete any ports, close any libraries, etc.
  73.  */
  74.  
  75. void DoExit(s,x1,x2,x3)
  76. char *s, *x1, *x2, *x3;
  77. {
  78.    long status = RETURN_OK;
  79.    
  80.    if (s != NULL)
  81.    {
  82.       printf(s,x1,x2,x3);
  83.       printf("\n");
  84.       status = RETURN_ERROR;
  85.    }
  86.    if (InputDevice)   CloseDevice(InputBlock);
  87.    if (InputBlock)    DeleteStdIO(InputBlock);
  88.    if (InputPort)     DeletePort(InputPort);
  89.    if (NamedPort)     DeletePort(NamedPort);
  90.    if (HandlerInfo)
  91.    {
  92.       if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
  93.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  94.    }
  95.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  96.    if (LayersBase)    CloseLibrary(LayersBase);
  97.    exit(status);
  98. }
  99.  
  100.  
  101. /*
  102.  *  CheckLibOpen()
  103.  *
  104.  *  General library open routine.  It opens a library and sets a pointer
  105.  *  to it.  It checks that the library was openned successfully.
  106.  */
  107.  
  108. void CheckLibOpen(lib,name,rev)
  109. APTR *lib;
  110. char *name;
  111. int rev;
  112. {
  113.    extern APTR OpenLibrary();
  114.  
  115.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  116.       DoExit("Can't open '%s'\n",name);
  117. }
  118.  
  119.  
  120. /*
  121.  *  Macros that make memory allocation easier.
  122.  */
  123. #define NEW(s,var)      (var = (struct s *)New("var",sizeof(struct s)))
  124. #define NEWCHAR(var,s)  (var = (char *)New("var",s))
  125.  
  126.  
  127. /*
  128.  *  New()
  129.  *
  130.  *  Allocate public memory of a given size and set it to all zeros.  If there
  131.  *  is not enough memory, then exit with an error, otherwise return the
  132.  *  pointer to the newly allocated memory.
  133.  */
  134.  
  135. APTR New(name,size)
  136. char *name;
  137. int size;
  138. {
  139.    APTR ptr;
  140.    
  141.    if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  142.       DoExit("Can't Get Memory for '%s'");
  143.    return(ptr);
  144. }
  145.  
  146.  
  147. /*
  148.  *  TellInputDevice()
  149.  *
  150.  *  Create a port and I/O block, and open the input device.  Set up the
  151.  *  I/O block to add or remove the input handler, and send the request
  152.  *  to the input device.  Finally, close the device and delete the
  153.  *  I/O block and port.
  154.  */
  155.  
  156. void TellInputDevice(function)
  157. int function;
  158. {
  159.    long status;
  160.  
  161.    if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
  162.    if ((InputBlock = CreateStdIO(InputPort)) == NULL)
  163.       DoExit("Can't Create Standard IO Block");
  164.    InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
  165.    if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
  166.    
  167.    InputBlock->io_Command = (long) function;
  168.    InputBlock->io_Data    = (APTR) &(HandlerInfo->Handler);
  169.    if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);
  170.  
  171.    CloseDevice(InputBlock);
  172.    DeleteStdIO(InputBlock);
  173.    DeletePort(InputPort);
  174. }
  175.  
  176.  
  177. /*
  178.  *  CreateHandler()
  179.  *
  180.  *  Open the libraries needed by the input handler and store their locations
  181.  *  in the HandlerInfo structure (so we can close them later).  Try to 
  182.  *  LoadSeg() the handler.  If it is not in the current directory, try the
  183.  *  L: directory.  Exit with an error if the handler can't be found.
  184.  *  Convert the segment pointer into a pointer to the Setup routine (the
  185.  *  first routine in the handler executable).  Call Setup() and pass it
  186.  *  the pointers to the libraries that it will need to use.  Setup() returns
  187.  *  a pointer to the actual handler routine that should be added into the
  188.  *  input handler chain.  Store this in the HandlerInfo structure so we
  189.  *  can use it to remove the handler later.  Set the handler priority to
  190.  *  51 so that it is ahead of Intuition.
  191.  *
  192.  *  Finally, add the handler in the chain and tell the user that the
  193.  *  handler has been installed.
  194.  */
  195.  
  196. void CreateHandler()
  197. {
  198.    long (*Setup)();
  199.  
  200.    CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  201.    CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
  202.  
  203.    HandlerInfo->Ibase = IntuitionBase;
  204.    HandlerInfo->Lbase = LayersBase;
  205.    if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
  206.       if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
  207.          DoExit("Can't Load '%s'",handler);
  208.    Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
  209.    HandlerInfo->Handler.is_Code = 
  210.       (void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase));
  211.    HandlerInfo->Handler.is_Node.ln_Pri = 51;
  212.  
  213.    TellInputDevice(IND_ADDHANDLER);
  214.    printf("%s %s (%s) Installed\n",program,version,date);
  215. }
  216.  
  217.  
  218. /*
  219.  *  Delete Handler()
  220.  *
  221.  *  Retreive the library pointers from the HandlerInfo structure where
  222.  *  we stored them when we originally installed the handler, then remove
  223.  *  the handler from the input handler chain.  Tell the user that the
  224.  *  handler is gone and then close the libraries that are no longer needed.
  225.  */
  226.  
  227. void DeleteHandler()
  228. {
  229.    IntuitionBase = HandlerInfo->Ibase;
  230.    LayersBase    = HandlerInfo->Lbase;
  231.  
  232.    TellInputDevice(IND_REMHANDLER);
  233.    UnLoadSeg(HandlerInfo->Segment);
  234.    printf("%s Removed\n",program);
  235.    
  236.    CloseLibrary(IntuitionBase);
  237.    CloseLibrary(LayersBase);
  238. }
  239.  
  240.  
  241. /*
  242.  *  main()
  243.  *
  244.  *  Check if a message port with our name already exists.
  245.  *  If not, then the handler is not already installed, so:
  246.  *    Allocate a new HandlerInfo structure and initialize the port name.
  247.  *    Create a public, names message-port (we will look for this the next
  248.  *      time HeliosMouse is called).
  249.  *    Make the message port point to the HandlerInfo structure so we
  250.  *      can use it later when the user asks us to remove the handler.
  251.  *      Note that the port is not actually used for putting and getting
  252.  *      messages, so the Task field is never used, so we can take it for
  253.  *      our own uses.
  254.  *    Finally, add the input handler into the chain.
  255.  *  Otherwise, the port exists, so HeliosMouse already is installed:
  256.  *    Retreive the HandlerInfo poiner from the port, and
  257.  *    remove the handler from the input handler chain.
  258.  *    Free the memory used by the HandlerInfo, and delete the message port.
  259.  */
  260.  
  261. void main()
  262. {
  263.    NamedPort = FindPort(PortName);
  264.    if (NamedPort == NULL)
  265.    {
  266.       NEW(HandlerBlock,HandlerInfo);
  267.       NEWCHAR(HandlerInfo->PortName,NAMESIZE);
  268.       strcpy(HandlerInfo->PortName,PortName);
  269.       if ((NamedPort = CreatePort(HandlerInfo->PortName,0)) == NULL)
  270.          DoExit("Can't Create Message Port '%s'",PortName);
  271.       NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
  272.       CreateHandler();
  273.    } else {
  274.       HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
  275.       DeleteHandler();
  276.       FreeMem(HandlerInfo->PortName,NAMESIZE);
  277.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  278.       DeletePort(NamedPort);
  279.    }
  280. }
  281.